import 'dart:async';
import 'dart:convert';
import 'dart:math';

import 'package:agora_rtc_engine/agora_rtc_engine.dart';
import 'package:flutter/cupertino.dart';
import 'package:gameplay_flutter/lib_rtc/rtc/rtc_manager.dart';
import 'package:gameplay_flutter/lib_runtime/utils/string_extend.dart';
import 'package:get/get.dart';
import 'package:path/path.dart' as Path;
import '../../../../../lib_baseview/utils/cache_util.dart';
import '../../../../../lib_baseview/widget/dialogs.dart';
import '../../../../../lib_runtime/logger.dart';
import '../../../../../lib_runtime/utils/num_util.dart';
import '../../../../../lib_runtime/utils/string_util.dart';
import '../../../../../resource/language/generated/l10n.dart';
import '../../../hall/room_main/room_rtc_rtm.dart';
import '../../../interface/root_proxy_model.dart';
import '../util/agora_music_util.dart';
import 'room_music_search_controller.dart';
import 'dart:io';

// 本地歌曲songId偏移量
var _localIdOffset = 111;

/// 房间音乐中心
class RoomMusicCenterController extends GetxController {
  /// 我喜欢的榜单
  static final _collectMusicCharts =
      MusicChartInfo(chartName: T.current!.i_like, id: 0x111);

  /// 我的音乐
  static final _mineMusicCharts =
      MusicChartInfo(chartName: T.current!.my_music, id: 0x222);

  static const playlistCacheKey = 'room_playlist';
  static const volumeCacheKey = 'room.music.volume';
  List<MusicChartInfo>? _musicCharts;

  MediaPlayer? _player;

  late StreamController<RequestMusicCollection> _musicCollectionStream;

  late StreamController<CollectedMusic> _collectedMusicStream;

  late MediaPlayerSourceObserver _mediaPlayerSourceObserver;

  final int _localId = 3300000000000000;

  double? _dragPercent;
  double _playingPercent = 0;
  int _positionMs = 0;

  /// 当前播放的音乐
  Music? _currentMusic;

  /// 是否静音
  bool _mute = false;

  /// 播放列表，历史
  List<Music> _playlist = [];

  // /// 正在播放音乐所在的列表
  // List<Music> _playinglist = [];

  /// 已缓存的音乐id
  final Set<int> _preloadedSongIds = {};

  /// 正在缓存的音乐ids
  final Set<int> _preloadingSongIds = {};

  /// 已收藏的音乐ids
  final List<CollectedMusic> _collectedMusics = [];

  /// 正在下载的歌词
  final Map<String, int> _loadingLyrics = {};

  /// 当前歌曲歌词
  var _curLyric = '';

  /// 是否显示歌词
  var _lyricShowing = false;

  /// 播放伴奏，默认false（播放原唱）
  var _accompany = false;

  List<CollectedMusic> get collectedMusics => _collectedMusics;

  String get localMusicDic =>
      '${'GlobalConfig.instance.appDirectory.path'}/upload';

  late PageController pageController;
  bool _showPlaylist = false;

  /// 播放模式
  PlayModel _playModel = PlayModel.listLoop;

  /// 音量
  int _volume = 50;
  bool _showVolume = false;
  double? _dragVolume;

  @override
  void onInit() {
    super.onInit();

    ///加载本地已缓存的id
    loadLocalPreloadedFile();
    // musicCenter.registerEventHandler(MusicContentCenterEventHandler(
    //     onMusicChartsResult: _onMusicChartsResult,
    //     onPreLoadEvent: _onPreLoadEvent,
    //     onMusicCollectionResult: _onMusicCollectionResult,
    //     onLyricResult: _onLyricResult));

    // _mediaPlayerSourceObserver = MediaPlayerSourceObserver(
    //     onPositionChanged: _onPositionChanged,
    //     onPlayerSourceStateChanged: _onPlayerSourceStateChanged);

    pageController = PageController();
    _musicCollectionStream = StreamController.broadcast();
    _collectedMusicStream = StreamController.broadcast();
  }

  MusicContentCenter get musicCenter =>
      RootProxyModel.instance!.roomRtcRtm!.musicCenter!;

  RoomRtcRtm get roomRtc => RootProxyModel.instance!.roomRtcRtm!;

  Future<MediaPlayer> createMediaPlayer({bool local = false}) async {
    var playerIsLocal = _player is! MusicPlayer;

    // 当前播放器匹配，复用
    if (_player != null && playerIsLocal == local) return _player!;

    if (_player != null) {
      // 当前播放器不匹配，销毁
      if (local != playerIsLocal) {
        _player!.unregisterPlayerSourceObserver(_mediaPlayerSourceObserver);
        await _player!.stop();
        await RtcManager.instance.rtcEngine.destroyMediaPlayer(_player!);
      }
    }

    // 创建播放器
    if (local) {
      _player = await RtcManager.instance.rtcEngine.createMediaPlayer();
    } else {
      _player = await roomRtc.musicCenter?.createMusicPlayer();
    }

    roomRtc.musicPlayerId = _player?.getMediaPlayerId() ?? 0;
    _player!.registerPlayerSourceObserver(_mediaPlayerSourceObserver);
    return _player!;
  }

  Stream<RequestMusicCollection> subscribeMusicCollection(String requestId) {
    return _musicCollectionStream.stream
        .where((event) => event.requestId == requestId);
  }

  /// onData: 增加收藏
  /// onError: 移除收藏
  Stream<CollectedMusic> get subscribeCollectedMusic =>
      _collectedMusicStream.stream;

  @override
  void onReady() {
    super.onReady();
    loadMusicCharts();
    int cacheVolume = CacheUtil.getInt(volumeCacheKey, 50);
    setVolume(cacheVolume);
    _initPlaylist();
  }

  @override
  void onClose() {
    musicCenter.unregisterEventHandler();
    _player?.unregisterPlayerSourceObserver(_mediaPlayerSourceObserver);
    _release();
    super.onClose();
  }

  /// 获取榜单
  Future<String> loadMusicCharts() => musicCenter.getMusicCharts();

  /// 获取榜单的音乐列表
  /// [mid] 榜单id
  Future<String> loadMusicList(int mid, {int page = 0, int pageSize = 20}) {
    return musicCenter.getMusicCollectionByMusicChartId(
        musicChartId: mid, page: page, pageSize: pageSize);
  }

  /// 搜索音乐列表
  /// [keyword] 搜索关键字
  Future<String> searchMusicList(String keyword,
      {int page = 0, int pageSize = 20}) {
    return musicCenter.searchMusic(
        keyWord: keyword, page: page, pageSize: pageSize);
  }

  /// 加入收藏
  Future<void> addToCollect(Music music) async {
    CollectedMusic collectedMusic = CollectedMusic(0, music);
    // var result =
    //     await RtcApi.instance.addCollect(jsonEncode(collectedMusic.toJson()));
    // if (result.isSuccess) {
    //   showToast(T.current!.collect_suc);
    //   collectedMusic.collectId = result.data?.id.toInt() ?? 0;
    //   _collectedMusicStream.add(collectedMusic);
    //   _collectedMusics.insert(0, collectedMusic);
    //   update([UpdateIds.collect]);
    // } else {
    //   showToast(T.current!.collect_fail);
    // }
  }

  /// 移除收藏
  /// 监听stream的onError
  Future<void> delFromCollectSongCode(int songCode) async {
    CollectedMusic music = _collectedMusics.singleWhere(
        (element) => element.music.songCode == songCode,
        orElse: () => CollectedMusic.def());
    if (music.collectId != 0) {
      delFromCollect(music);
    }
  }

  /// 移除收藏
  /// 监听stream的onError
  Future<void> delFromCollect(CollectedMusic music) async {
    // var result = await RtcApi.instance.delCollect(music.collectId);
    // if (result.isSuccess) {
    //   showToast(T.current!.cancel_collect_suc);
    //   update([UpdateIds.collect]);
    //   _collectedMusicStream.addError(music);
    //   _collectedMusics.remove(music);
    //   update([UpdateIds.collect]);
    // } else {
    //   showToast(T.current!.cancel_collect_fail);
    // }
  }

  /// 音乐榜单回调
  // void _onMusicChartsResult(String requestId, List<MusicChartInfo> result,
  //     MusicContentCenterStatusCode status) {
  //   _musicCharts = [];
  //   if (result.isNotEmpty) {
  //     _musicCharts!.add(result.firstWhere(
  //         (element) =>
  //             element.chartName?.contains(T.current!.recommend) ?? false,
  //         orElse: () => result.first));
  //     _musicCharts!.add(result.firstWhere(
  //         (element) =>
  //             element.chartName?.contains(T.current!.new_music) ?? false,
  //         orElse: () => result.last));
  //   }
  //   _musicCharts!.add(_collectMusicCharts);
  //   _musicCharts!.add(_mineMusicCharts);
  //   update();
  // }

  void _downLoadMusic(Music music) async {
    int songCode = music.songCode ?? 0;
    // var response = await DownloadManager.download(
    //     music.releaseTime ?? '', getLocalMusicFilePathWithId(songCode));
    // if (response.statusCode == 200) {
    //   _preloadingSongIds.remove(songCode);
    //   _preloadedSongIds.add(songCode);
    //   RLog.d('_onPreLoadEvent---$songCode--${_currentMusic?.songCode}');
    //   if (_currentMusic?.songCode == songCode) {
    //     _openSong(songCode);
    //   }
    //   update([UpdateIds.playState]);
    // } else {
    //   _preloadingSongIds.remove(songCode);
    //   showToast(response.statusMessage ?? T.current!.download_fail);
    //   update([UpdateIds.playState]);
    // }
  }

  /// preload 回调
  // void _onPreLoadEvent(int songCode, int percent, String lyricUrl,
  //     PreloadStatusCode status, MusicContentCenterStatusCode errorCode) {
  //   switch (status) {
  //     case PreloadStatusCode.kPreloadStatusCompleted:
  //       _preloadingSongIds.remove(songCode);
  //       _preloadedSongIds.add(songCode);
  //       RLog.d('_onPreLoadEvent---$songCode--${_currentMusic?.songCode}');
  //       if (_currentMusic?.songCode == songCode) {
  //         _openSong(songCode);
  //       }
  //       update([UpdateIds.playState]);
  //       break;
  //     case PreloadStatusCode.kPreloadStatusFailed:
  //       _preloadingSongIds.remove(songCode);
  //       showToast(T.current!.download_fail);
  //       update([UpdateIds.playState]);
  //       break;
  //   }
  // }

  // /// 音乐资源列表回调
  // void _onMusicCollectionResult(String requestId, MusicCollection result,
  //     MusicContentCenterStatusCode status) {
  //   _handleMusicCollectionStatus(RequestMusicCollection(requestId, result));
  // }

  // void _onLyricResult(String requestId, String lyricUrl,
  //     MusicContentCenterStatusCode status) async {
  //   var songCode = _loadingLyrics[requestId];

  //   if ((songCode ?? 0) <= 0) return;

  //   var success = await AgoraMusicUtil.downloadLyric(songCode ?? 0, lyricUrl);

  //   if (!success) return;
  //   if (_currentMusic?.songCode != songCode) return;
  //   _curLyric = await AgoraMusicUtil.getLyricString(songCode!);

  //   if (_curLyric.isNotEmpty) update([UpdateIds.lyricChange]);
  // }

  /// 播放进度回调
  /// [positionMs] 单位毫秒
  void _onPositionChanged(int positionMs) {
    if (_currentMusic != null && _currentMusic!.durationS != null) {
      _positionMs = positionMs;
      _playingPercent = positionMs / (_currentMusic!.durationS! * 1000);
      update([UpdateIds.positions, UpdateIds.lyricChange]);
    }
  }

  /// 播放器状态变化
  /// [state] 等于playerStateOpenCompleted，才可play
  // void _onPlayerSourceStateChanged(
  //     MediaPlayerState state, MediaPlayerError ec) {
  //   if (ec == MediaPlayerError.playerErrorNone) {
  //     switch (state) {
  //       case MediaPlayerState.playerStateOpenCompleted:
  //         playSelf();
  //         break;
  //       case MediaPlayerState.playerStatePlaying:
  //         bool has = _playlist
  //             .any((element) => element.songCode == _currentMusic?.songCode);
  //         if (!has) {
  //           _playlist.insert(0, _currentMusic!);
  //           update([UpdateIds.playList]);
  //         }
  //         break;
  //       case MediaPlayerState.playerStatePlaybackCompleted:
  //       case MediaPlayerState.playerStatePlaybackAllLoopsCompleted:
  //         playNext();
  //         break;
  //       default:
  //         break;
  //     }
  //     update([UpdateIds.playState]);
  //   }
  // }

  List<MusicChartInfo>? get musicCharts => _musicCharts;

  bool isCollected(Music item) {
    return _collectedMusics
        .any((element) => element.music.songCode == item.songCode);
  }

  Future<MediaPlayerState> playState(Music? item) async {
    if (item?.songCode != currentMusic?.songCode) {
      return Future.value(MediaPlayerState.playerStateIdle);
    }
    return _player!.getState();
  }

  void play(Music item) async {
    RLog.d('play-----$item');
    if (item.songCode == null || item.songCode == 0) {
      showToast(T.current!.this_song_cant_play);
      return;
    }

    int songCode = item.songCode!;
    var player = await createMediaPlayer(local: isLocalMusicCode(songCode));
    if (_currentMusic?.songCode != item.songCode) {
      MediaPlayerState state = await player.getState();
      RLog.d('play---$player--$state');
      if (state != MediaPlayerState.playerStateIdle) {
        await player.stop();
      }
      _currentMusic = item;
      _positionMs = 0;
      _playingPercent = 0;
      _curLyric = '';
      _accompany = false;

      ///文件已缓存 开始播放
      if (isPreloaded(item)) {
        _openSong(songCode);
      } else {
        if (!_preloadingSongIds.contains(songCode)) {
          _preloadingSongIds.add(songCode);

          ///本地歌曲缓存
          if (isLocalMusicCode(songCode)) {
            _downLoadMusic(item);
          } else {
            // musicCenter.preload(songCode: songCode);
          }
        }
      }

      if (_lyricShowing) toggleLyric(show: _lyricShowing);
      update([UpdateIds.playState, UpdateIds.positions, UpdateIds.lyricChange]);
    } else {
      if (_playModel == PlayModel.singleCycle) {
        player.play();
      } else {
        MediaPlayerState state = await player.getState();
        if (state == MediaPlayerState.playerStatePlaying) {
          player.pause();
        } else {
          player.play();
        }
      }
    }
  }

  void _openSong(int songCode) async {
    if (isLocalMusicCode(songCode)) {
      _player?.open(url: checkLocalMusicFilePath(songCode), startPos: 0);
    } else if (_player is MusicPlayer) {
      (_player as MusicPlayer).openWithSongCode(songCode: songCode);
    }
  }

  bool isMusicLoading(Music? item) {
    int songCode = item?.songCode ?? 0;
    return _preloadingSongIds.contains(songCode);
  }

  bool isPreloaded(Music item) {
    return _preloadedSongIds.contains(item.songCode);
  }

  Music? get currentMusic => _currentMusic;

  String get playingTime {
    if (_currentMusic == null) {
      return '00:00';
    }
    return StringUtil.formatAudioTime(_positionMs ~/ 1000);
  }

  int get positionMs => _positionMs;

  String get currentDuration {
    if (_currentMusic == null) {
      return '00:00';
    }
    return StringUtil.formatAudioTime(_currentMusic!.durationS ?? 0);
  }

  double get playingPercent {
    if (_dragPercent != null) {
      return _dragPercent!;
    }
    return _playingPercent > 1.0 ? 1.0 : _playingPercent;
  }

  set dragPercent(double? percent) {
    _dragPercent = percent;
    update([UpdateIds.positions, UpdateIds.lyricChange]);
  }

  bool isShowCancel = false;

  /// 设置是否有关闭按钮
  void cancelBtn(bool isShow) {
    isShowCancel = isShow;
    update(["is_show"]);
  }

  void seekTo(double value) {
    _player?.seek((_currentMusic!.durationS! * 1000 * value).toInt());
  }

  void playSelf() async {
    var state = await _player?.getState();
    if (state == MediaPlayerState.playerStatePlaying) {
      _player?.pause();
    } else {
      _player?.play();
    }
  }

  void toggleMute() {
    _mute = !_mute;
    _player?.mute(_mute);
    update();
  }

  bool get mute => _mute;

  List<Music> get playlist => _playlist;

  set playlist(List<Music> list) {
    _playlist = list;
    update([UpdateIds.playList]);
  }

  // set playinglist(List<Music> list) {
  //   _playinglist = list;
  // }

  void playPre() {
    if (_currentMusic == null) {
      return;
    }
    int index = _playlist.indexOf(_currentMusic!);
    int preIndex = _playModel.genPreIndex(index, _playlist.length);
    play(_playlist[preIndex]);
  }

  /// 播放下一首
  void playNext() {
    if (_currentMusic == null) {
      return;
    }
    int index = _playlist.indexOf(_currentMusic!);
    int nextIndex = _playModel.genNextIndex(index, _playlist.length);
    play(_playlist[nextIndex]);
  }

  void togglePlaylist() {
    _showPlaylist = !_showPlaylist;
    pageController.animateToPage(_showPlaylist ? 1 : 0,
        duration: const Duration(milliseconds: 300), curve: Curves.linear);
  }

  bool get hasMultiTrack => (_currentMusic?.type ?? 0) == 4;

  bool get accompany => _accompany;
  toggleAccompany() {
    _accompany = !_accompany;
    _player?.selectAudioTrack(_accompany ? 1 : 0);
  }

  bool get lyricShowing =>
      _lyricShowing && _curLyric.isNotEmpty && _currentMusic != null;

  String get curLyric => _curLyric;

  Future<void> toggleLyric({bool? show}) async {
    var songCode = _currentMusic?.songCode ?? 0;

    if (isLocalMusicCode(songCode)) return;

    if (show != null) {
      _lyricShowing = show;
    } else {
      _lyricShowing = !_lyricShowing;
    }

    if (!_lyricShowing) {
      // showToast('关闭歌词');
    } else {
      // showToast('打开歌词');
      if (!(await AgoraMusicUtil.isLyricDownload(songCode))) {
        var requestId = await musicCenter.getLyric(songCode: songCode);
        _loadingLyrics[requestId] = songCode;
      } else {
        _curLyric = await AgoraMusicUtil.getLyricString(songCode);
      }
    }
    update([UpdateIds.lyricChange]);
  }

  int get volume {
    if (_dragVolume != null) {
      return (_dragVolume! * 100).toInt();
    }
    return _volume;
  }

  bool get showVolume => _showVolume;

  Future setVolume(int volume) async {
    await _player?.adjustPlayoutVolume(volume);
    await _player?.adjustPublishSignalVolume(volume);
    _volume = volume;
    update([UpdateIds.volumeChanged]);
    CacheUtil.setInt(volumeCacheKey, _volume);
  }

  void toggleVolume() {
    _showVolume = !_showVolume;
    update([UpdateIds.toggleVolume]);
  }

  set dragVolume(double? percent) {
    _dragVolume = percent;
    update([UpdateIds.volumeChanged]);
  }

  double get dragVolume => (_dragVolume ?? 0) * 100;

  /// 处理音乐列表，获取是否preload状态
  void _handleMusicCollectionStatus(RequestMusicCollection data) async {
    int count = data.result.getCount();
    RLog.d('_handleMusicCollectionStatus == $count');
    for (int i = 0; i < count; i++) {
      int code = data.result.getMusic(i).songCode ?? 0;
      if (code == 0) continue;
      bool has = await musicCenter.isPreloaded(code);
      if (has) {
        _preloadedSongIds.add(code);
      }
    }
    RLog.d('_handleMusicCollectionStatus == $_preloadedSongIds');
    _musicCollectionStream.add(data);
  }

  _release() async {
    if (_player != null) {
      await _player!.stop();
      await roomRtc.destroyMediaPlayer(_player!);
    }
    _player = null;
  }

  /// 设置收藏列表
  void updateCollectStatus(List<CollectedMusic> data) {
    _collectedMusics.clear();
    _collectedMusics.addAll(data);
    update([UpdateIds.collect]);
  }

  PlayModel get playModel => _playModel;

  /// 更改播放模式
  void changePlayModel() {
    List<PlayModel> models = PlayModel.values;
    int index = models.indexOf(_playModel);
    index++;
    if (index >= models.length) {
      index = 0;
    }
    _playModel = models[index];
    update([UpdateIds.playModel]);
  }

  Future savePlaylist() async {
    if (_playlist.isEmpty) return false;
    return CacheUtil.saveBean(playlistCacheKey, _playlist.toList());
  }

  void _initPlaylist() async {
    List? cache = await CacheUtil.getBean<List>(playlistCacheKey);
    if (cache != null && cache.isNotEmpty) {
      _playlist = cache.map<Music>((item) => Music.fromJson(item)).toList();
    }
  }

  void showSearch(String value) {
    pageController.jumpToPage(2);
    Get.find<RoomMusicSearchController>().search(value);
  }

  void dismissSearch() {
    pageController.jumpToPage(0);
    Get.find<RoomMusicSearchController>().dismiss();
  }

  void clearPlaylist() async {
    _playlist.clear();
    var state = await _player?.getState();
    if (state != MediaPlayerState.playerStateIdle) {
      _player?.stop();
      _currentMusic = null;
      _positionMs = 0;
      _playingPercent = 0;
      _curLyric = '';
    }
    update([
      UpdateIds.playState,
      UpdateIds.playList,
      UpdateIds.positions,
      UpdateIds.lyricChange
    ]);
  }

  ///是否是本地音乐（本地上传的非版权音乐）
  bool isLocalMusicCode(int songCode) {
    if (songCode > _localId && songCode.toString().startsWith('33')) {
      return true;
    }
    return false;
  }

  ///根据SongId生成音乐文件地址 tos下载音乐时使用
  String getLocalMusicFilePathWithId(int songId) {
    return '$localMusicDic/$songId';
  }

  int get localSongCode {
    _localIdOffset += 1;
    return DateTime.now().millisecondsSinceEpoch + _localId + _localIdOffset;
  }

  ///生成本地音乐文件名地址
  String getLocalMusicFilePath(String fileName, int songCode) {
    int index = fileName.lastIndexOf(".");
    String ext = fileName.safeSubstring(index + 1).toLowerCase();
    String path = '$localMusicDic/$songCode.$ext';
    return path;
  }

  ///本地是否已经存在上传歌曲缓存
  String checkLocalMusicFilePath(int songId) {
    final directory = Directory(localMusicDic);
    if (directory.existsSync()) {
      final List<FileSystemEntity> files = directory.listSync();
      for (final file in files) {
        if (file is File) {
          String fileName = Path.basenameWithoutExtension(file.path);
          if (fileName == songId.toString()) {
            return file.path;
          }
        }
      }
    }
    return '';
  }

  loadLocalPreloadedFile() {
    final directory = Directory(localMusicDic);
    if (directory.existsSync()) {
      final List<FileSystemEntity> files = directory.listSync();
      for (final file in files) {
        if (file is File) {
          String fileName = Path.basenameWithoutExtension(file.path);
          int songId = NumUtil.parseInt(fileName, 0);
          if (isLocalMusicCode(songId) && !_preloadedSongIds.contains(songId)) {
            _preloadedSongIds.add(songId);
          }
        }
      }
    } else {
      directory.create(recursive: true);
    }
  }
}

class RequestMusicCollection {
  final String requestId;
  final MusicCollection result;

  RequestMusicCollection(this.requestId, this.result);
}

/// 收藏的音乐
class CollectedMusic {
  late int collectId;
  late Music music;

  CollectedMusic.def() {
    collectId = 0;
    music = const Music();
  }

  CollectedMusic(this.collectId, this.music);

  CollectedMusic.fromJson(this.collectId, Map<String, dynamic> data) {
    music = Music.fromJson(data);
  }

  Map<String, dynamic> toJson() => music.toJson();
}

/// 局部更新的id集合
class UpdateIds {
  static const collect = 'music.collect';
  static const playState = 'music.playState';
  static const positions = 'music.positions';
  static const playModel = 'music.playModel';
  static const playList = 'music.playList';
  static const toggleVolume = 'music.toggleVolume';
  static const volumeChanged = 'music.volumeChanged';
  static const lyricChange = 'music.lyric';
}

/// 播放模式
/// <br/>[listLoop] 列表循环
/// <br/>[singleCycle] 单曲循环
/// <br/>[shuffle] 随机播放
enum PlayModel {
  listLoop,
  singleCycle,
  shuffle,
}

extension PlayModelExt on PlayModel {
  String get assetPath {
    String assetPath = 'music/music_paly_type_cycle.svg';
    if (this == PlayModel.shuffle) {
      assetPath = 'music/music_play_type_random.svg';
    } else if (this == PlayModel.singleCycle) {
      assetPath = 'music/music_paly_type_single.svg';
    }
    return assetPath;
  }

  int genNextIndex(int currentIndex, int length) {
    switch (this) {
      case PlayModel.listLoop:
        currentIndex++;
        if (currentIndex >= length) {
          currentIndex = 0;
        }
        break;
      case PlayModel.singleCycle:
        break;
      case PlayModel.shuffle:
        currentIndex = (Random().nextDouble() * length).toInt();
        break;
    }
    return currentIndex;
  }

  int genPreIndex(int currentIndex, int length) {
    switch (this) {
      case PlayModel.listLoop:
        currentIndex--;
        if (currentIndex < 0) {
          currentIndex = length - 1;
        }
        break;
      case PlayModel.singleCycle:
        break;
      case PlayModel.shuffle:
        currentIndex = (Random().nextDouble() * length).toInt();
        break;
    }
    return currentIndex;
  }
}
